package com.atguigu.gmall.activity.receiver;

import com.atguigu.gmall.activity.mapper.SeckillGoodsMapper;
import com.atguigu.gmall.activity.service.SeckillGoodsService;
import com.atguigu.gmall.common.constant.MqConst;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.service.RabbitService;
import com.atguigu.gmall.common.util.DateUtil;
import com.atguigu.gmall.model.activity.SeckillGoods;
import com.atguigu.gmall.model.activity.UserRecode;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.rabbitmq.client.Channel;
import lombok.SneakyThrows;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

/**
 * @Author: zm
 * @Date: 2021/8/31 20:14
 */
@Component
public class SeckillReceiver {

    @Autowired
    private SeckillGoodsMapper seckillGoodsMapper;

    @Autowired
    private SeckillGoodsService seckillGoodsService;

    @Autowired
    private RedisTemplate redisTemplate;

    // 将当天秒杀的商品添加到redis 缓存中 监听定时任务
    @SneakyThrows
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = MqConst.QUEUE_TASK_1, durable = "true", autoDelete = "false"),
            exchange = @Exchange(MqConst.EXCHANGE_DIRECT_TASK),
            key = {MqConst.ROUTING_TASK_1}
    ))
    public void DbToCache(String msg, Message message, Channel channel) {

        System.out.println(msg);
        try {
            // 根据条件将当天秒杀的商品从数据库查询出来
            QueryWrapper<SeckillGoods> seckillGoodsQueryWrapper = new QueryWrapper<>();
            seckillGoodsQueryWrapper.eq("status", "1");
            seckillGoodsQueryWrapper.eq("DATE_FORMAT(`start_time`,'%Y-%m-%d')", DateUtil.formatDate(new Date()));
            seckillGoodsQueryWrapper.ge("stock_count", 0);
            List<SeckillGoods> seckillGoods = seckillGoodsMapper.selectList(seckillGoodsQueryWrapper);

            // 将查询出来的商品添加redis缓存中
            for (SeckillGoods seckillGood : seckillGoods) {
//                // 如果已经存在就结束本次循环
//                if (redisTemplate.opsForHash().hasKey(RedisConst.SECKILL_GOODS, seckillGood.getSkuId().toString())) {
//                    continue;
//                }
                if (redisTemplate.boundHashOps(RedisConst.SECKILL_GOODS).hasKey(seckillGood.getSkuId().toString())) {
                    continue;
                }
                redisTemplate.opsForHash().put(RedisConst.SECKILL_GOODS, seckillGood.getSkuId().toString(), seckillGood);

                Integer num = seckillGood.getNum();
                // 为了防止超卖 将秒杀的数量 放到 redis的list中
                for (Integer i = 0; i < num; i++) {
                    redisTemplate.opsForList().leftPush(RedisConst.SECKILL_STOCK_PREFIX + seckillGood.getSkuId(), seckillGood.getSkuId().toString());
                }

                // 每个商品的状态位 通过 redis的 发布与订阅实现  开始时状态为 值为1  "46:1"  每个redis服务都应该订阅这个管道
                redisTemplate.convertAndSend("seckillpush", seckillGood.getSkuId() + ":1");
            }
        } catch (Exception e) {
            // 记录日志
            e.printStackTrace();
        }
        // 手动确认消息
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
    }


    @SneakyThrows
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = MqConst.QUEUE_SECKILL_USER, durable = "true", autoDelete = "false"),
            exchange = @Exchange(MqConst.EXCHANGE_DIRECT_SECKILL_USER),
            key = {MqConst.QUEUE_SECKILL_USER}
    ))
    // 监听秒杀队列
    public void seckillQueue(UserRecode userRecode, Message message, Channel channel) {

        try {
            if (userRecode == null) {
                return;
            }
            // todo 预下单
            seckillGoodsService.seckillOrder(userRecode.getUserId(), userRecode.getSkuId());
        } catch (Exception e) {
            // 记录日志
            e.printStackTrace();
        }

        // 手动确认消息
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
    }

}
